package com.lean.reptile.JsoupXPath;
import com.google.common.collect.Lists;

import com.google.common.collect.Maps;
import lombok.Data;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import org.jsoup.nodes.Element;
import org.jsoup.nodes.Node;
import org.seimicrawler.xpath.JXDocument;
import org.seimicrawler.xpath.JXNode;

import java.io.*;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * @ClassName: XpathDemo
 * @Description:  XPath是一种表达式语言，它的返回值可能是节点，节点集合，原子值，以及节点和原子值的混合等
 * JsoupXPath是基于Jsoup的拓展，使用路径的形式解析XML和HTML文档。核心类为JXDocument。JsoupXPath的节点对象JXNode不仅可以获取标签节点，还可以获取属性节点。
 * @Author: zhanghongwei
 * @Date: 2022/5/7 17:33
 */
public class XpathDemo {
    /**
     * <dependency>
     *     <groupId>cn.wanghaomiao</groupId>
     *     <artifactId>JsoupXpath</artifactId>
     *     <version>2.2.1</version>
     * </dependency>
     */


//    语法:
//        选取结点
//             /	从根节点选取
//             //	从匹配选择的当前节点选择文档中的节点，而不考虑它们的位置。
//             .	选取当前结点
//             ..	选取当前节点的父结点
//             @	选取属性
//
//        比如：
//            bookstore	选取 bookstore 元素的所有子节点。
//            /bookstore	选取根元素 bookstore。注释：假如路径起始于正斜杠( / )，则此路径始终代表到某元素的绝对路径！
//            bookstore/book	选取属于 bookstore 的子元素的所有 book 元素。
//            //book	选取所有 book 子元素，而不管它们在文档中的位置。
//             bookstore//book	选择属于 bookstore 元素的后代的所有 book 元素，而不管它们位于 bookstore 之下的什么位置。
//            //@lang	选取名为 lang 的所有属性。
//       谓语：
//             表达式	                            描述
//            /bookstore/book[1]	                选取属于 bookstore 子元素的第一个 book 元素。
//            /bookstore/book[last()]	            选取属于 bookstore 子元素的最后一个 book 元素。
//            /bookstore/book[last()-1]	        选取属于 bookstore 子元素的倒数第二个 book 元素。
//            /bookstore/book[position()<3]	    选取最前面的两个属于 bookstore 元素的子元素的 book 元素。
//            //title[@lang]	                    选取所有拥有名为 lang 的属性的 title 元素。
//            //title[@lang='eng']	            选取所有 title 元素，且这些元素拥有值为 eng 的 lang 属性。
//            /bookstore/book[price>35.00]	    选取 bookstore 元素的所有 book 元素，且其中的 price 元素的值须大于 35.00。
//            /bookstore/book[price>35.00]/title	选取 bookstore 元素中的 book 元素的所有 title 元素，且其中的 price 元素的值须大于 35.00。
//
//

//    全文搜索路径
//    在全局搜索对应的标签，不需要从根目录开始搜索
//    "//元素"                                                           全局搜索元素
//
//    "//元素/子元素或@元素属性"                      全局搜索元素后的子路径中找子元素或属性

//    条件筛选语法
//    根据条件筛选过滤节点，前面部分为筛选的条件，后面可以加上操作的动作
//    //元素[@属性=value]                                                                               筛选属性为value值的节点对象
//    //元素[@属性=value]/text()        //元素[@属性=value]/html()          获取元素为value值的标签体内容对象
//        选取未知节点：
//            通配符	描述
//            *	匹配任何元素节点。
//            @*	匹配任何属性节点。
//            node()	匹配任何类型的节点。
//
//            如：
//                /bookstore/*	选取 bookstore 元素的所有子元素。
//                //*	选取文档中的所有元素。
//                //title[@*]	选取所有带有属性的 title 元素。

            //https://www.runoob.com/xpath/xpath-tutorial.html

    public static void xpathTest(){
        //基于URL创建JXDocument
        JXDocument jxd = JXDocument.createByUrl("http://www.w3school.com.cn/b.asp");
        //Xpath语句
        String str = "//*[@id='course']/ul/li/a";
        //获取节点集合
        List<JXNode> list = jxd.selN(str);
        //遍历节点
        for (int i = 0; i < list.size(); i++) {
            JXNode node = list.get(i);
            System.out.println("标题为:" + node.asElement().text() + "\tURL为:" + node.asElement().attr("href"));
        }
    }

    public static  void  test(){
        try {
            Document document = Jsoup.connect("https://auto.gasgoo.com/").get();
            JXDocument jxd = JXDocument.create(document);
//            List<JXNode> jxNodes = jxd.selN("//*/dl[@class='lastNews']/dt/a");
            List<JXNode> jxNodes = jxd.selN("//div/div/ul/li/a");
            for(JXNode jxNode : jxNodes){
                Element element = jxNode.asElement();
                System.out.println(element.text());
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }


    // https://blog.csdn.net/test253506088/article/details/119538300
    // https://blog.csdn.net/test253506088/article/details/119538096
    public static  void test1(){
        Document document = null;
        try {
            document = Jsoup.connect("https://www.bilibili.com/").get();
        } catch (IOException e) {
            e.printStackTrace();
        }
        JXDocument jxDocument = JXDocument.create(document);
        List<JXNode> jxNodes = jxDocument.selN("//*[@id=\"i_cecream\"]/div[1]/div[3]/div[2]/div[1]/a");
        for(JXNode jxNode : jxNodes){
            Element element = jxNode.asElement();
            System.out.println(element.text());
        }
    }

    public static  void test3(){
        Document document = null;
        try {
            document = Jsoup.connect("https://www.ibge.gov.br/explica/codigos-dos-municipios.php").get();
        } catch (IOException e) {
            e.printStackTrace();
        }
        List<Region> list=new ArrayList<>();
        JXDocument jxDocument = JXDocument.create(document);
        List<JXNode> jxNodes = jxDocument.selN("//div[@class=\"container-codigos\"]/table[1]/tbody[@class=\"codigos-list\"]");
        for(JXNode jxNode : jxNodes){
            Element element = jxNode.asElement();
            List<Node> nodes = element.childNodes();
            for (Node node : nodes) {
                if(node!=null && StringUtils.isNotEmpty(node.toString().trim())){
                    String name=node.childNodes().get(0).childNodes().get(0).childNodes().get(0).toString();
                    String values=node.childNodes().get(1).childNodes().get(0).childNodes().get(0).toString();
                    Region region=new Region();
                    region.setName(name);
                    region.setValue(values);
                    list.add(region);
                }
            }
        }

        int index=2;
        for (Region region : list) {
            List<Region> regions=new ArrayList<>();
            List<JXNode> nodesList = jxDocument.selN("//div[@class=\"container-codigos\"]/table[" + index + "]/tbody[@class=\"codigos-list\"]");
            JXNode jxNode = nodesList.get(0);
            List<Node> nodes = jxNode.asElement().childNodes();
            for (Node node : nodes) {
                if(node!=null && StringUtils.isNotEmpty(node.toString().trim())&& CollectionUtils.isNotEmpty(node.childNodes()) && node.childNodes().size()>1){
                    String value=node.childNodes().get(1).childNodes().get(0).toString();
                    String name=node.childNodes().get(0).childNodes().get(0).childNodes().get(0).toString();
                    Region region1=new Region();
                    region1.setName(name);
                    region1.setValue(value);
                    regions.add(region1);
                }
            }
            region.setChildren(regions);
            index++;
        }
        try {
            list.stream().forEach(region -> {
                String name = region.getName();
                String value=region.getValue();
                List<Region> children = region.getChildren();
                if(CollectionUtils.isNotEmpty(children)){
                    children.stream().forEach(region1 -> {
                        String sql="INSERT INTO `upseller`.`t_ibge_city_code` (`name`, `code`, `pid_name`, `pid_code`, `create_time`, `update_time`) VALUES (\""+region1.getName()+"\", "+region1.getValue()+", \""+name+"\", "+value+", now(), now());";
                        System.out.println(sql+"\n");

                    });
                }
            });
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
    //Xsoup是我基于Jsoup开发的一款XPath解析器。
    public static void main(String[] args) {
        test3();
//        xpathTest();
    }
}
@Data
class Region{
    String name;
    String value;
    List<Region> children;
}
